package org.create.builder;

import org.create.bean.FieldInfo;
import org.create.bean.TableInfo;
import org.create.utils.DateTool;
import org.create.utils.IoTool;
import org.create.utils.LogTool;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static org.create.bean.Constants.*;


public class BuildMappers {
    private static BufferedWriter bw;

    private static void buildPackageComment(TableInfo tableInfo) throws IOException {
        bw.write("package " + PACKAGE_BASE + "." + PACKAGE_MAPPERS + ";");
        appendLine(2);
        bw.write("import org.apache.ibatis.annotations.Param;");
        appendLine(3);
    }

    private static void buildDescriptionComment(TableInfo tableInfo) throws IOException {
        bw.write("/**");
        appendLine();
        bw.write(" * Description " + tableInfo.getComment());
        appendLine();
        bw.write(" * date " + DateTool.DateFormat(new Date(), YMD_HMS));
        appendLine();
        bw.write(" */");
        appendLine();
    }

    private static void buildClassComment(TableInfo tableInfo) throws IOException {
        bw.write("public interface " + tableInfo.getBeanName() + "Mapper<T, P>" + " extends BaseMapper<T, P> {");
        appendLine();
        buildFieldComment(tableInfo.getKeyIndexMap());
    }

    private static void buildFieldComment(Map<String, List<FieldInfo>> keyIndexMap) throws IOException {
        for (Map.Entry<String, List<FieldInfo>> entry : keyIndexMap.entrySet()) {
            List<FieldInfo> fieldInfoList = entry.getValue();
            StringBuilder sb = new StringBuilder();
            StringBuilder params = new StringBuilder();
            int firstLoop = 1;
            for (FieldInfo fieldInfo : fieldInfoList) {
                sb.append(fieldInfo.getPropertyName().substring(0, 1).toUpperCase()).append(fieldInfo.getPropertyName().substring(1));
                params.append("@Param(\"").append(fieldInfo.getPropertyName()).append("\")").append(" ").append(fieldInfo.getJavaType()).append(" ").append(fieldInfo.getPropertyName());
                if (firstLoop < fieldInfoList.size()) {
                    sb.append("And");
                    params.append(", ");
                    firstLoop++;
                }
            }
            buildFieldDescriptionComment(sb + "获取对象");
            bw.write("    T selectBy" + sb + "(" + params + ");");
            appendLine(2);
            buildFieldDescriptionComment(sb + "更新");
            bw.write("    Integer updateBy" + sb + "(@Param(\"bean\") T t, " + params + ");");
            appendLine(2);
            buildFieldDescriptionComment(sb + "删除");
            bw.write("    Integer deleteBy" + sb + "(" + params + ");");
            appendLine(2);
        }
        bw.write("}");
    }

    private static void buildFieldDescriptionComment(String comment) throws IOException {
        bw.write("    /**");
        appendLine();
        bw.write("     * 根据" + comment);
        appendLine();
        bw.write("     */");
        appendLine();
    }

    private static void appendLine() throws IOException {
        appendLine(1);
    }

    private static void appendLine(int loop) throws IOException {
        if (loop == 1) {
            bw.newLine();
        } else {
            for (int i = 0; i < loop; i++) {
                bw.newLine();
            }
        }
    }

    public static void run(List<TableInfo> tableInfoList) {
        for (TableInfo tableInfo : tableInfoList) {
            File file = new File(PATH_MAPPERS + tableInfo.getBeanName() + "Mapper" + JAVA_SUFFIX);
            File dir = file.getParentFile();
            boolean d = dir.mkdirs();
            LogTool.printLog(d, "新建目录", dir);
            try {
                boolean r = file.createNewFile();
                LogTool.printLog(r, "新建文件", file);
                bw = IoTool.createBw(file);
                buildPackageComment(tableInfo);
                buildDescriptionComment(tableInfo);
                buildClassComment(tableInfo);
            } catch (Exception e) {
                LogTool.printError(e);
            } finally {
                IoTool.close();
            }
        }
    }
}
